//
//  UIImage+Ext.m
//  WebJs
//
//  Created by lizq on 16/9/14.
//  Copyright © 2016年 lizq. All rights reserved.
//

#import "UIImage+Ext.h"
#import <objc/runtime.h>

static void *KeyWord = (void *) @"Keword";
static void *KeyLayer = (void *) @"KeyLayer";

@implementation UIImage(Ext)

- (NSString *)keyWord {
    return objc_getAssociatedObject(self, KeyWord);
}

- (void)setKeyWord:(NSString *)keyWord {
    objc_setAssociatedObject(self, KeyWord, keyWord, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (CALayer *)layer {
    return objc_getAssociatedObject(self, KeyLayer);
}

- (void)setLayer:(CALayer *)layer {
    objc_setAssociatedObject(self, KeyLayer, layer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

/**
 * theme color
 */
- (UIColor *)themeColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1
    int bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
#else
    int bitmapInfo = kCGImageAlphaPremultipliedLast;
#endif
    
    //第一步 先把图片缩小 加快计算速度. 但越小结果误差可能越大
    CGSize thumbSize=CGSizeMake(100, 100);
    
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL,
                                                 thumbSize.width,
                                                 thumbSize.height,
                                                 8,//bits per component
                                                 thumbSize.width*4,
                                                 colorSpace,
                                                 bitmapInfo);
    
    CGRect drawRect = CGRectMake(0, 0, thumbSize.width, thumbSize.height);
    CGContextDrawImage(context, drawRect, self.CGImage);
    CGColorSpaceRelease(colorSpace);
    
    //第二步 取每个点的像素值
    unsigned char* data = CGBitmapContextGetData (context);
    if (data == NULL) return nil;
    NSMutableArray *colors = [[NSMutableArray alloc] initWithCapacity:1];
    for(int offset = 0; offset < thumbSize.width * thumbSize.height; offset += 4) {
        @autoreleasepool {
            int red = data[offset];
            int green = data[offset+1];
            int blue = data[offset+2];
            Color *color = [[Color alloc] initWithR:red green:green blue:blue];
            [colors addObject:color];
        }
    }
    CGContextRelease(context);
    
    return [self kmeasColor:colors];
}

- (UIColor *)kmeasColor:(NSArray *)items {
    // 随机选取10个中心点
    NSMutableArray *centers = [[NSMutableArray alloc] initWithCapacity:1];
    for(int i = 0; i < 10 && i < items.count; i++) {
        int index = arc4random()%items.count;
        [centers addObject:items[index]];
    }
    BOOL isEnd = YES;
    do {
        isEnd = YES;
        // 步骤2 根据10个中心点分类
        NSArray *classes = [self newClasses:items centers:centers];
        // 步骤3 获得新的类聚中心
        NSArray *newCenters = [self newCenters:classes];
        // 步骤4 比较
        for(int i = 0; i < 10; i++) {
            Color *old = [centers objectAtIndex:i];
            Color *new = [newCenters objectAtIndex:i];
            if([new distanceToObject:old] > sqrt(100)) {
                //未结束
                isEnd = NO;
            }
        }
        centers = [newCenters mutableCopy];
        // 获得主题色
        if(isEnd) {
            return  [self getThemeColor:classes center:centers];
        }
    } while(isEnd == NO);
    return nil;
}

/**
 * 步骤2 获得新的类聚
 */
- (NSArray *)newClasses:(NSArray *)data centers:(NSArray *)centers {
    // 步骤2 根据10个中心点分类
    NSMutableArray *classes = [[NSMutableArray alloc] initWithCapacity:1];
    for(int i = 0;i < 10;i++) {
        NSMutableArray *class = [[NSMutableArray alloc] initWithCapacity:1];
        [classes addObject:class];
    }
    
    for(Color * item in data) {
        @autoreleasepool {
            NSMutableArray *ds = [[NSMutableArray alloc] initWithCapacity:10];
            for(int i = 0; i < centers.count;i++) {
                int d = [item distanceToObject:centers[i]];
                [ds addObject:@(d)];
            }
            // 比较获得最小值的位置
            int minIndex = [self indexOfMin:ds];
            [classes[minIndex] addObject:item];
        }
    }
    return [classes mutableCopy];
}

// 步骤3
- (NSArray *)newCenters:(NSArray *)classes {
    // 步骤3 获得新的类聚中心
    NSMutableArray *newCenters = [[NSMutableArray alloc] initWithCapacity:10];
    for(NSArray *cs in classes) {
        @autoreleasepool {
            Color *nc = [self newCenterObject:cs];
            [newCenters addObject:nc];
        }
    }
    return [newCenters mutableCopy];
}

/**
 * 获得主题色
 */
- (UIColor *)getThemeColor:(NSArray *)classes center:(NSArray *)centers {
    int max = 0;
    for(int i = 0; i < classes.count; i ++) {
        if([[classes objectAtIndex:max] count] < [[classes objectAtIndex:i] count]) {
            max = i;
        }
    }
    Color *color = [centers objectAtIndex:max];
    return  [UIColor colorWithRed:color.r/255.0 green:color.g/255.0 blue:color.b/255.0 alpha:1];
    
}

// 获得数组最小值
- (int)indexOfMin:(NSArray *)numbers {
    int min = 0;
    for(int i = 1; i < numbers.count; i++) {
        if([numbers[min] intValue] > [numbers[i] intValue]) {
            min = i;
        }
    }
    return min;
}

/**
 * 获得数组的新类聚中心
 */
- (Color *)newCenterObject:(NSArray *)data {
    
    int r = 0, g = 0, b = 0;
    for(Color *obj in data) {
        r += obj.r;
        g += obj.g;
        b += obj.b;
    }
    r = r / data.count+1;
    g = g / data.count+1;
    b = b / data.count+1;
    return  [[Color alloc] initWithR:r green:g blue:b];
}

@end



#pragma mark ---
#pragma mark Color
@implementation Color
- (instancetype)initWithR:(int)r green:(int)g blue:(int)b {
    self = [super init];
    if(self) {
        _r = r;
        _g = g;
        _b = b;
    }
    return self;
}

- (int)distanceToObject:(Color *)obj {
    return  sqrt(pow(abs(_r - obj.r), 2) + pow(abs(_g - obj.g), 2) + pow(abs(_b - obj.b), 2));
}

- (BOOL)compare:(Color *)color {
    return _r == color.r && _g == color.g && _b == color.b;
}

@end
